const randomInt = (max, min = 0) => {
  return Math.floor(Math.random() * (max - min + 1) + min);
};
const randomFloat = (max, min = 0) => {
  return Math.random() * (max - min + 0.1) + min;
};

// 烟花的颜色列表，鲜艳的红色、橙色和黄色、绿色、蓝色和紫色
const colors = [
  "#FF0000", // 红色
  "#FFA500", // 橙色
  "#FFFF00", // 黄色
  "#00FF00", // 绿色
  "#00FFFF", // 蓝色
  "#FF00FF", // 紫色
];

const randomColor = () => {
  return colors[randomInt(colors.length - 1)];
};

// 粒子效果
class Particle {
  x = 0; // 粒子的x坐标
  y = 0; // 粒子的y坐标
  speedX = randomFloat(3, -3); // 粒子的水平速度
  speedY = randomFloat(3, -3); // 粒子的垂直速度
  gravity = 0.005; // 粒子的重力加速度
  size = 2; // 粒子的大小
  color; // 粒子的颜色
  // 透明度
  alpha = 255;
  trajectory = []; // 粒子的轨迹

  context; // 画布的上下文

  constructor(x, y, color, ctx) {
    this.x = x;
    this.y = y;
    this.color = color;
    this.context = ctx;
  }

  update() {
    this.x += this.speedX; // 更新粒子的水平位置
    this.y += this.speedY; // 更新粒子的垂直位置
    this.speedY += this.gravity; // 更新粒子的垂直速度，考虑重力加速度
    this.gravity += 0.002; // 更新重力加速度
    this.alpha -= randomInt(4, 1); // 更新粒子的透明度
    this.trajectory.unshift({ x: this.x, y: this.y }); // 将当前位置添加到轨迹中
  }

  draw() {
    if (this.alpha <= 0) return;
    const ctx = this.context;
    ctx.globalAlpha = this.alpha / 255;
    ctx.fillStyle = this.color;
    ctx.beginPath();
    ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
    ctx.fill();
    // 绘制拖尾粒子效果
    let alpha = this.alpha;
    const length = this.trajectory.length > 20 ? 20 : this.trajectory.length;
    let size = this.size;
    for (let i = 0; i < length; i++) {
      const { x, y } = this.trajectory[i];
      ctx.globalAlpha = alpha / 255;
      ctx.fillStyle = this.color;
      ctx.beginPath();
      ctx.arc(x, y, size, 0, Math.PI * 2);
      ctx.fill();
      alpha -= 16;
      size -= 0.05;
      if (alpha <= 0) return;
    }
  }
}

class Rocket {
  startX = 0; // 火箭的起始x坐标
  startY = 0; // 火箭的起始y坐标
  x = 0; // 火箭的x坐标
  y = 0; // 火箭的y坐标
  maxHeight = 0; // 火箭的最大高度(画布高度)
  exploded = false; // 标记火箭是否已经爆炸
  particlesFinished = false; // 标记爆炸粒子是否已经全部消失
  speedY = randomInt(-8, -5); // 火箭的上升速度
  color = randomColor(); // 火箭颜色

  context = null; // 画布上下文

  // 轨迹方向
  direction = randomFloat(1);
  // 轨迹
  trajectory = [];

  // 爆炸粒子列表
  particles = [];

  constructor(startX, startY, ctx, maxHeight) {
    this.startX = startX; // 火箭的起始x坐标
    this.startY = startY; // 火箭的起始y坐标
    this.x = startX; // 火箭的起始x坐标
    this.y = startY; // 火箭的起始y坐标
    this.context = ctx;
    this.maxHeight = maxHeight; // 火箭的最大高度(画布高度)
  }

  // 爆炸
  explode() {
    if (this.particlesFinished) return;
    this.particles = this.particles
      .filter((p) => p.alpha > 0)
      .map((p) => {
        p.update();
        p.draw();
        return p;
      });
  }

  // 更新火箭状态，包括位置和爆炸逻辑
  update() {
    if (this.exploded) return;

    this.y += this.speedY; // 更新火箭的位置
    if (Math.abs(this.x - this.startX) > 5) this.direction *= -1; // 更新火箭的轨迹方向
    this.x += this.direction; // 更新火箭的位置
    this.trajectory.unshift({ x: this.x, y: this.y }); // 将当前位置添加到轨迹中

    if (this.y < randomInt(this.maxHeight, this.maxHeight / 2) / 3) {
      // 生成爆炸粒子
      Array.from({ length: randomInt(150, 120) }).forEach((_, i) => {
        const color = i % 2 === 0 ? this.color : "#ffffff";
        this.particles.push(new Particle(this.x, this.y, color, this.context));
      });
      // 爆炸
      this.exploded = true;
    }
  }

  // 绘制未爆炸的火箭
  draw() {
    if (!this.exploded) {
      const ctx = this.context;
      // 绘制火箭
      ctx.beginPath();
      // 绘制一个向上的三角形
      ctx.fillStyle = this.color;
      ctx.globalAlpha = 1;
      ctx.moveTo(this.x, this.y - 6);
      ctx.lineTo(this.x - 3, this.y);
      ctx.lineTo(this.x + 3, this.y);
      ctx.fill();

      ctx.beginPath();
      // 绘制一个矩形
      ctx.rect(this.x - 3, this.y, 6, 8);
      ctx.fill();
      // 绘制轨迹粒子效果
      const len = this.trajectory.length > 10 ? 10 : this.trajectory.length;
      let alpha = 255;
      for (let i = 0; i < len; i += 1) {
        ctx.beginPath();
        ctx.globalAlpha = alpha / 255;
        const { x, y } = this.trajectory[i];
        ctx.arc(randomFloat(x + 3, x - 3), y + 15, 1, 0, 2 * Math.PI);
        ctx.fill();
        alpha -= 8;
        if (alpha <= 0) return;
      }
    } else {
      this.explode();
      if (!this.particles.length) {
        this.particlesFinished = true;
      }
    }
  }
}

class Firework {
  rockets = []; // 存储火箭的数组
  width = window.innerWidth; // 画布宽度
  height = window.innerHeight; // 画布高度
  context = null; // 画布上下文
  runing = false; // 标记是否正在运行

  constructor(context, width, height) {
    this.context = context;
    if (width) this.width = width;
    if (height) this.height = height;
  }

  // 创建火箭
  createRocket() {
    const startX = randomInt(this.width - 50, 50); // 随机生成火箭的起始x坐标
    const startY = this.height - 20; // 火箭的起始y坐标为画布高度
    const rocket = new Rocket(startX, startY, this.context, this.height); // 创建一个新的火箭
    this.rockets.push(rocket); // 将火箭添加到数组中
    return rocket;
  }

  // 更新所有火箭的状态
  update() {
    this.context.clearRect(0, 0, this.width, this.height);
    this.rockets = this.rockets
      .filter((rocket) => !rocket.particlesFinished)
      .map((rocket) => {
        rocket.update();
        rocket.draw();
        return rocket;
      });
  }

  run() {
    this.runing = true;
    this.update();
    if (this.rockets.length) {
      // 使用requestAnimationFrame来递归调用run方法
      requestAnimationFrame(() => this.run());
    } else {
      this.runing = false;
    }
  }

  start() {
    this.createRocket(); // 创建一个新的火箭
    if (!this.runing) {
      this.run();
    }
  }
}
